#! /usr/bin/env groovy
pipeline {
  agent { label 'docker' }
  environment {
    DOCKERHUB_RW_USERNAME = 'svcmaterials'
    GIT_SUBJECT = sh (
        script: 'git show --format=oneline --no-patch',
        returnStdout: true
    ).trim()
    GIT_AUTHOR = sh (
        script: 'git show -s --pretty=%an',
        returnStdout: true
    ).trim()
    SERVICE_NAME = 'canvas-rce-api'
    STARLORD_IMAGE_TAG = 'starlord.inscloudgate.net/jenkins/canvas-rce-api'
  }
  options {
    ansiColor("xterm")
    timeout(time: 50, unit: 'MINUTES')
    disableConcurrentBuilds()
  }
  stages {
    stage('Build and Push Docker Images') {
      parallel {
        stage('Cloudgate') {
          steps {
            withCredentials([sshUserPrivateKey(credentialsId: '44aa91d6-ab24-498a-b2b4-911bcb17cc35', keyFileVariable: 'SSH_KEY_PATH', usernameVariable: 'SSH_USERNAME')]) {
              sh '''
                GIT_SSH_COMMAND='ssh -i "$SSH_KEY_PATH" -l "$SSH_USERNAME"' git clone --depth 1 ssh://${GERRIT_HOST}:29418/RichContentService
              '''
            }

            dir('RichContentService') {
              withCredentials([sshUserPrivateKey(credentialsId: '44aa91d6-ab24-498a-b2b4-911bcb17cc35', keyFileVariable: 'SSH_KEY_PATH', usernameVariable: 'SSH_USERNAME')]) {
                sh '''
                  GIT_SSH_COMMAND='ssh -i "$SSH_KEY_PATH" -l "$SSH_USERNAME"' git submodule update --init
                '''
              }

              cloudgateBuild(cgEnvironment: "build", cgVersion: "12.0", tfVersion: "0.13")
            }
          }
          post {
            failure {
                slackSend channel: "#mat-bots", color: 'danger', message: "${env.SERVICE_NAME}: CG build failed (<${env.BUILD_URL}|Open>). Changes: \n - ${env.GIT_SUBJECT} [${env.GIT_AUTHOR}]"
            }
            success {
                slackSend channel: "#mat-bots", color: 'good', message: "${env.SERVICE_NAME}: CG build successful (<${env.BUILD_URL}|Open>). Changes: \n - ${env.GIT_SUBJECT} [${env.GIT_AUTHOR}]"
            }
          }
        }
        stage(':latest') {
          steps {
            script {
              withMultiPlatformBuilder {
                withCredentials([string(credentialsId: 'dockerhub-materials-rw', variable: 'DOCKERHUB_RW_PASSWORD')]) {
                  sh 'echo $DOCKERHUB_RW_PASSWORD | docker login --username $DOCKERHUB_RW_USERNAME --password-stdin'
                }

                sh """
                  docker buildx build \
                    --builder multi-platform-builder \
                    --pull \
                    --push \
                    --platform=linux/amd64,linux/arm64 \
                    --tag "${STARLORD_IMAGE_TAG}:latest" \
                    --tag "${STARLORD_IMAGE_TAG}:master" \
                    --tag instructure/canvas-rce-api:latest \
                    .
                """
              }
            }
          }
        }
        stage('New Release') {
          // When the git tag starts with the letter "v" followed by one or more digits, we know this commit is a new release
          when { tag pattern: "v\\d+", comparator: "REGEXP"}

          // We use an environment variable instead of a Groovy variable here because combining env var interpolation
          // with Groovy interpolation in a multiline Jenkins pipeline string is fraught with problems.
          environment {
            VERSION = sh (
              script: "docker-compose run --rm web node -p \"require('./package.json').version\"",
              returnStdout: true
            ).trim()
          }

          steps {
            script {
              withCredentials([string(credentialsId: 'dockerhub-materials-rw', variable: 'DOCKERHUB_RW_PASSWORD')]) {
                sh 'echo $DOCKERHUB_RW_PASSWORD | docker login --username $DOCKERHUB_RW_USERNAME --password-stdin'
              }

              // We don't want to cause a conflict by reusing an existing builder container, so we first remove it if it exists.
              sh 'docker buildx rm another-multi-platform-builder || true'

              // Calling the withMultiPlatformBuilder() function in a parallel stage can cause conflicts and fail the
              // build, so we create our own builder container for this stage.
              sh "docker buildx create --platform arm64,amd64 --name another-multi-platform-builder"

              sh """
                docker buildx build \
                  --builder another-multi-platform-builder \
                  --pull \
                  --push \
                  --platform=linux/amd64,linux/arm64 \
                  --tag "${STARLORD_IMAGE_TAG}:${VERSION}" \
                  --tag "instructure/canvas-rce-api:release-${VERSION}" \
                  .
              """
            }
          }
        }
      }
    }
  }
  post {
    cleanup {
      sh 'docker logout "https://index.docker.io/v1/"'
      sh 'docker buildx rm another-multi-platform-builder || true'
    }
  }
}
